package com.limit.aspect.core;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.core.annotation.AnnotatedElementUtils;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

/**
 * @title: AnnotationAspectTemplate
 * @Author xu-xiang
 * @Date: 2024-3-26 13:54:10
 * @description: 注解AOP模板
 */
public abstract class AnnotationAspectTemplate implements BeanFactoryAware, AnnotationAspectOperations {

    private static final Logger logger = LoggerFactory.getLogger(AnnotationAspectTemplate.class);

    private RateLimitingStrategyService strategyService;

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.strategyService = beanFactory.getBean(RateLimitingStrategyService.class);
    }

    @Override
    @Around("pointcut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        Annotation limitAnnotation = this.getMergedAnnotation(joinPoint.getTarget(), method);
        strategyService.doRedisLua(limitAnnotation, method);
        return joinPoint.proceed();
    }

    public Annotation getMergedAnnotation(Object targetObject, Method method) {
        Class<? extends Annotation> annotationType = pointcutAnnotationClass();
        // 获取方法级别注解
        Annotation annotation = AnnotatedElementUtils.getMergedAnnotation(method, annotationType);

        // 获取类级别注解
        if (annotation == null) {
            annotation = AnnotatedElementUtils.getMergedAnnotation(targetObject.getClass(), annotationType);
        }

        return annotation;
    }
}
